using GZ.Common.Data;
using Newtonsoft.Json;
using GZ.DB.Repository.wcs_hy;
using GZ.DB.Entity.wcs_hy;
using GZ.DB.IRepository.wcs_hy;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Configuration;
using GZ.Projects.WCS_SVC;
using System.Net.NetworkInformation;
using GZ.Common.Code;

namespace GZ.Projects.WCS_SVC
{

	#region IC01.AGV作业任务操作
	/// <summary>
	/// wcs下发agv任务下发接口参数
	/// </summary>
	[Serializable]
	/*	00表示：位置编号
		01表示：物料批次号
		02表示：策略编号（含多个区域）如：第一个区域放不下, 可以放第二个区域
		03表示：货架编号，通过货架编号找到货架所在位置
		04表示：区域编号，在区域中查找可用位置
		05表示：仓位编号（叉车/CTU 专用）
		06表示：巷道编号
		07表示：容器编号
		08表示：巷道策略
		09表示：巷道区域
		10表示：巷道仓位
		11表示：输送线（机台）编号
		12表示：CTU 工作台（梳齿工作站）编号
		13表示：搬运巷道指定货架出库
	 */

	public class ToAgvOperateTask
	{
		public string reqCode; //请求编号

		//这里引入判空不显示字段
		[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
		public string taskTyp; //任务模板

		[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
		public string wbCode; //工作位

		[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
		public List<AgvStep> positionCodePath; //取放货点位置

		[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
		public string podCode; //任务编号

		[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
		public string agvCode; //AGV编号
		
		[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
		public string taskCode; //任务编号（不能重复,任务继续时需要发taskCode小车的任务单头）
		
		[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
		public string reqTime;
		
		[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
		public string ctnrCode;
		
		[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
		public string data;//任务编号（可以重复）
	}
	#endregion
	// 定义AGV步骤数据结构
	public class AgvStep
	{
		public string positionCode { get; set; }
		public string type { get; set; }
	}

	// 定义位置代码路径结构，匹配你的JSON格式
	public class PositionCodePath
	{
		public List<AgvStep> positionCodePath { get; set; }
	}
	/// <summary>
	/// agv与wcs交互的返回值
	/// </summary>
	[Serializable]
	public class wcsToAgvResponse
	{
		public string code;
		public string message;
		public string reqCode;
	}
	#region IC02.AGV作业任务上报
	/// <summary>
	/// agv上报wcs任务状态参数
	/// </summary>
	[Serializable]
	public class FromAgvCallBack
	{
		public string reqCode; //请求编号
		public string method; //方法名称
		public string taskTyp; //任务模版
		public string taskCode; //任务单号
		public string wbCode; //工作位
		public string podCode; //货架编号
		public string robotCode; //agv编号
		public string ctnrCode;
		public string data;//任务编号（可以重复）
	}
	#endregion
	
	public class WCSTOAGV
	{
		private static string _url = string.Empty;
		public bool ToAgvOperateTask(ToAgvOperateTask toAgvOperateTask,string direction, out string message,out string responseCode)
		{
			string msg = $"\r\n[wcs下发任务信息至AGV：Start{DateTime.Now:yyyy/MM/dd HH:mm:ss:fff}";
			message = null;
			responseCode = "99";  //系统出现的异常也让他进行重发
			//wcsToAgvResponse response = new wcsToAgvResponse();
			try
			{
				switch (direction)
				{
					case "1":
						//下发任务
						_url = ConfigurationManager.AppSettings["createAgvTask"];
						break;
					case "2":
						//继续任务
						_url = ConfigurationManager.AppSettings["continueAgvTask"];
						break;
					case "3":
						//取消任务
						_url = ConfigurationManager.AppSettings["cancelAgvTask"];
						break;
					default:
						message = "未知操作类型";
						return false;
				}
				//设置隐藏字段
				string input = JsonConvert.SerializeObject(toAgvOperateTask, Formatting.None, new JsonSerializerSettings
				                                           {
				                                           	NullValueHandling = NullValueHandling.Ignore
				                                           });
				msg += $"\r\n\t下发json:[{input}]{DateTime.Now:yyyy/MM/dd HH:mm:ss:fff}";
				//string json = new HttpClient().Call(input, url, out errorMsg);
				string json = new HttpClient().Call("POST",input, _url, out message,out int resCode);
				msg += $"\r\n\t收到回复json:[{json}]{DateTime.Now:yyyy/MM/dd HH:mm:ss:fff}";
				wcsToAgvResponse response = Json.ToObject<wcsToAgvResponse>(json);
				//AGV接口文档中 0 失败 1成功
				if (response != null && response.code == "0")
				{
					message = json;
					responseCode = response.code;
					return true;
				}
				else
				{
					message = json;
					responseCode = response.code;
					return false;
				}
			}
			catch (Exception ex)
			{
				msg += ex.Message;
				message = ex.Message;
				return false;
			}
			finally
			{
				msg = msg.Replace('\'', '\"');
				Conn.HYlog.Info(1, $"WCS下发任务至AGV ", 1, msg);
			}
		}
	}


	public static class ToAgvHandle
	{
		/// <summary>
		/// 任务回复 ToWmsResponseOrderData JSON 文本
		/// </summary>
		private static string BuildResponseToAgv( string code, string message , string reqCode = null)
		{
			// 截断 msg 到 256 字符,系统异常返回值太长，需要截断
			if (!string.IsNullOrEmpty(message) && message.Length > 64)
				message = message.Substring(0, 64);
			var resp = new wcsToAgvResponse
			{
				code = code,
				message = message,
				reqCode = reqCode
			};
			return JsonConvert.SerializeObject(resp);
		}
		
		/// <summary>
		/// IC01.AGV任务状态获取
		/// </summary>
		/// <param name="requestJson"></param>
		/// <returns></returns>
		public static string GetAgvCallBack(string requestJson)
		{
			//string respJson = string.Empty;
			//1-任务开始，2-取货中，3-取货完成，4-放货中，5-放货完成，6-任务取消，7-异常
			try
			{
				var request = JsonConvert.DeserializeObject<FromAgvCallBack>(requestJson);
				//1. 检查请求参数是否为空
				if (request == null)
				{
					return BuildResponseToAgv("-1", "请求参数为空");
				}
				else
				{
					if (string.IsNullOrEmpty(request.reqCode))
					{
						return BuildResponseToAgv("-1", "请求编号不可为空");
					}

					if (string.IsNullOrEmpty(request.method) || string.IsNullOrEmpty(request.taskCode))
					{
						return BuildResponseToAgv("-1", "请求任务编号或方法不可为空", request.reqCode);
					}
					AutoScanApp auto = new AutoScanApp();
					//2.根据任务编号查询任务
					AgvTaskRepository agvTaskRepository = new AgvTaskRepository();
					AgvTaskEntity agvTask = agvTaskRepository.FindEntity(t => t.task_no == request.data && t.task_state != "End");
					if (agvTask == null)
					{
						return BuildResponseToAgv("-1", "请求的任务号业务数据库中任务不存在",request.reqCode);
					}
					else
					{
						
						if (request.method == "start" || request.method == "end")
						{
							agvTask.task_state = request.method == "start" ? "Start" : "End";
							agvTask.LastUpdatedTime = DateTime.Now;
							agvTask.reverse_2 = request.taskCode;
							if (request.method == "end")
							{
								agvTask.TaskEndTime = DateTime.Now;
							}

							bool dbres = auto.UpdateAgvTask(agvTask, out string error);
							return BuildResponseToAgv("0", "success", request.reqCode);
						}
						if(request.method == "cancel")
						{
							var mainTask = new MainMissionRepository().FindEntity(t=> t.task_no == agvTask.task_no );
							if(mainTask == null)
							{
								return BuildResponseToAgv("-2", $"返回的任务号{agvTask.task_no}主任务不存在", request.reqCode);
							}
							mainTask.MissionState = "Cancel";
							mainTask.LastUpdatedTime = DateTime.Now;
							agvTask.task_state = "Cancel";
							agvTask.LastUpdatedTime = DateTime.Now;
							//2.通知WMS任务取消，agv作业失败
							SystemSynchronizationEntity systemSynchronization = new SystemSynchronizationEntity();
							systemSynchronization.syn_direction = 2;
							systemSynchronization.syn_status = 0;
							systemSynchronization.ope_type = "7";
							systemSynchronization.task_no = agvTask.task_no;
							systemSynchronization.tray_code = agvTask.tray_code;
							systemSynchronization.cur_pos = agvTask.frm_pos;
							systemSynchronization.ope_time = DateTime.Now;
							systemSynchronization.err_cnt = 0;
							
							bool resSys = auto.UpdateMainAndAgvTaskAndInsertSysTask(mainTask,agvTask,systemSynchronization,out string cancelErr);
							if(!resSys)
							{
								return BuildResponseToAgv("-1", cancelErr, request.reqCode);
							}
							return BuildResponseToAgv("0", "success", request.reqCode);
						}
						var agvTaskStep = new AgvCarryStepRepository().FindEntity(t => t.task_type == agvTask.agv_task_type && t.step_method == request.method);
						//3.步骤模板是否正确配置符合约定
						if(agvTaskStep == null)
						{
							return BuildResponseToAgv("-1", "请求的任务步骤不存在", request.reqCode);
						}
						//4.检查步骤编号是否重复上报
						if (agvTaskStep.step_seq == agvTask.step_no)
						{
							return BuildResponseToAgv("-1", "重复的报告处理",request.reqCode);
						}
						//5. 检查当前位置并判断是否记绑通知wms
						switch (agvTaskStep.position_code)
						{
								//起点取货完成
							case  "[FROM_POS]":
							case  "[FROM_POS_2]":
								//1.通知线体取货完成
								// 如果是 FROM_POS_2，需要先通知线体
								if (agvTaskStep.position_code == "[FROM_POS_2]")
								{
									string plcPrefix = agvTask.frm_pos.StartsWith("1010") ? "TPPLC_1" :
										agvTask.frm_pos.StartsWith("2010") ? "TPPLC_2" : null;

									if (plcPrefix != null)
									{
										Conn.HYRedis.SetValue(
											$"{plcPrefix}.WCS_OUTFINISHSENT_{agvTask.frm_pos}",
											"1",
											$"{plcPrefix}Queue"
										);
									}
								}
								//2.通知WMS取货完成
								SystemSynchronizationEntity systemSynchronization = new SystemSynchronizationEntity();
								systemSynchronization.syn_direction = 2;
								systemSynchronization.syn_status = 0;
								systemSynchronization.ope_type = "4";
								systemSynchronization.task_no = agvTask.task_no;
								systemSynchronization.tray_code = agvTask.tray_code;
								systemSynchronization.cur_pos = agvTask.frm_pos;
								systemSynchronization.ope_time = DateTime.Now;
								systemSynchronization.err_cnt = 0;
								
								agvTask.step_no = agvTaskStep.step_seq;
								agvTask.task_state = "Doing";
								agvTask.LastUpdatedTime = DateTime.Now;
								agvTask.reverse_1 = request.robotCode ?? "NULL";
								bool sysRes = auto.UpdateAgvAndInsertSysTask(agvTask,systemSynchronization,out string dbErr);
								if (!sysRes)
								{
									return BuildResponseToAgv("-1", dbErr, request.reqCode);
								}
								break;
								//终点放货完成
							case "[TO_POS_2]":
							case "[TO_POS]":
								//1. [TO_POS_2] 才需要通知线体卸货完成
								if (agvTaskStep.position_code == "[TO_POS_2]")
								{
									if (agvTask.to_pos.StartsWith("1010"))
									{
										Conn.HYRedis.SetValue($"TPPLC_1.WCS_INFINISHSENT_{agvTask.to_pos}", "1", "TPPLC_1Queue");
										Conn.HYRedis.SetValue($"TPPLC_1.WCS_TASKNO_{agvTask.to_pos}", agvTask.device_task_no, "TPPLC_1Queue");
									}
									if (agvTask.to_pos.StartsWith("2010"))
									{
										Conn.HYRedis.SetValue($"TPPLC_2.WCS_INFINISHSENT_{agvTask.to_pos}", "1", "TPPLC_2Queue");
										Conn.HYRedis.SetValue($"TPPLC_2.WCS_TASKNO_{agvTask.to_pos}", agvTask.device_task_no, "TPPLC_2Queue");
									}
								}

								//2. 通知WMS卸货完成
								var system = new SystemSynchronizationEntity();
								system.syn_direction = 2;
								system.syn_status = 0;
								system.ope_type = "5";
								system.task_no = agvTask.task_no;
								system.tray_code = agvTask.tray_code;
								system.cur_pos = agvTask.to_pos;
								system.ope_time = DateTime.Now;
								system.err_cnt = 0;

								agvTask.step_no = agvTaskStep.step_seq;
								agvTask.task_state = "Finish";
								agvTask.LastUpdatedTime = DateTime.Now;
								
								var mainTask = new MainMissionRepository().FindEntity(t => t.task_no == agvTask.task_no);
								if (mainTask == null)
									return BuildResponseToAgv("-1", "任务主表不存在", request.reqCode);
								
								
								mainTask.InteStationNo = agvTask.to_pos;
								bool sysResTo = auto.UpdateAgvAndInsertSysTask(agvTask, system, out string dbErrTo);
								if (!sysResTo)
									return BuildResponseToAgv("-2", "数据库更新异常" + dbErrTo, request.reqCode);

								//3. 更新主任务
								if (!agvTask.to_pos.StartsWith("1010") && !agvTask.to_pos.StartsWith("2010"))
								{
									mainTask.MissionState = "Finish";
									mainTask.MissionEndTime = DateTime.Now;
									mainTask.LastUpdatedTime = DateTime.Now;

									var system2 = new SystemSynchronizationEntity();
									system2.syn_direction = 2;
									system2.syn_status = 0;
									system2.ope_type = "2";
									system2.task_no = agvTask.task_no;
									system2.tray_code = agvTask.tray_code;
									system2.cur_pos = agvTask.to_pos;
									system2.ope_time = DateTime.Now;
									system2.err_cnt = 0;

									bool sysRes2 = auto.UpdateMainAndInsertSysTask(mainTask, system2, out string dbErr2);

									if (!sysRes2)
										return BuildResponseToAgv("-1", dbErr2, request.reqCode);
								}
								else
								{
									bool rm = auto.updateMainTask(mainTask, out string e11);
									if (!rm)
										return BuildResponseToAgv("-1", e11, request.reqCode);
								}
								break;
								// 需要询问线体是否可取,根据任务的任务起始位置
							case "[FROM_POS_1]":
								if (agvTask.frm_pos.StartsWith("1010"))
								{
									agvTask.task_condition = "TPPLC_1.PLC_CANOUT_" + agvTask.frm_pos;
								}
								if (agvTask.frm_pos.StartsWith("2010"))
								{
									agvTask.task_condition = "TPPLC_2.PLC_CANOUT_" + agvTask.frm_pos;
								}
								//因为设备变量不能用中横线，必须用下划线
								if(agvTask.frm_pos.StartsWith("RJJBW"))
								{
									agvTask.task_condition = "TPPLC_1." + agvTask.frm_pos.Replace("-", "_");
								}
								agvTask.step_no = agvTaskStep.step_seq;
								agvTask.req_type = "2";   //请求任务继续
								agvTask.task_state = "Continue";
								agvTask.LastUpdatedTime = DateTime.Now;

								bool res = auto.UpdateAgvTask(agvTask, out string err);
								if (!res)
								{
									return BuildResponseToAgv("-1", err, request.reqCode);
								}
								break;
							case "[TO_POS_1]":
								if (agvTask.to_pos.StartsWith("1010"))
								{
									agvTask.task_condition = "TPPLC_1.PLC_CANIN_" + agvTask.to_pos;
								}
								if (agvTask.to_pos.StartsWith("2010"))
								{
									agvTask.task_condition = "TPPLC_2.PLC_CANIN_" + agvTask.to_pos;
								}
								if(agvTask.to_pos.StartsWith("RJJBW"))
								{
									agvTask.task_condition = "TPPLC_1." + agvTask.to_pos.Replace("-", "_");
								}
								agvTask.step_no = agvTaskStep.step_seq;
								agvTask.req_type = "2";  //请求任务继续
								agvTask.task_state = "Continue";
								agvTask.LastUpdatedTime = DateTime.Now;

								bool res1 = auto.UpdateAgvTask(agvTask,out string err1);
								if (!res1)
								{
									return BuildResponseToAgv("-1", err1, request.reqCode);
								}
								break;

						}
						return BuildResponseToAgv("0", "success",request.reqCode);
					}
				}
			}
			catch (Exception ex)
			{
				return BuildResponseToAgv("-1", ex.Message);
			}
			
		}

	}
}